#pragma once

#include "Expression.h"

namespace mbase {

	delegate bool QueryLambda(MetroClass^ obj);

ref class Query {
private:
	String^ className;
	String^ var;
	String^ UID;
	Expression^ expr;
	QueryLambda^ lambda;
public:
	static Expression^ expression(Expression^ e) { return e; }
	static Expression^ expression(bool b) { return ref new AtomicExpression(ref new IntValue(b ? 1 : 0)); }
	Query(String^ c, String^ v, Expression^ e, QueryLambda^ l) : className(c), var(v), expr(e), lambda(l) {}
	Query(String^ c, String^ _uid) : className(c), UID(_uid) {}
	String^ GetClassName() { return className; }
	String^ GetUID() { return UID; }
	virtual MetroClass^ createObject(String^ uid) { return nullptr; }
	bool evaluateNatively(MetroClass^ obj) { return lambda != nullptr ? lambda(obj) : true; }
	Value^ evaluate(int val) { return evaluate(ref new IntValue(val)); }
	Value^ evaluate(String^ val) { return evaluate(ref new StringValue(val)); }
	Value^ evaluate(MetroClass^ val) { return evaluate(ref new ObjectValue(val)); }
	Value^ evaluate(Value^ val) {
		if (nullptr == expr) return ref new IntValue(1);
		auto vars = ref new Map<String^,Value^>;
		vars->Insert(var, val);
		return expr->evaluate(vars);
	}
};

}
